home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / OldSrc / CH11 / SRC / OBJPGON3.CLS < prev    next >
Text File  |  1996-05-04  |  19KB  |  699 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4. END
  5. Attribute VB_Name = "ObjPolygon"
  6. Attribute VB_Creatable = False
  7. Attribute VB_Exposed = False
  8. Option Explicit
  9.  
  10. ' Point3D is defined in module M3OPS.BAS as:
  11. '    Type Point3D
  12. '        coord(1 To 4) As Single
  13. '        trans(1 To 4) As Single
  14. '    End Type
  15.  
  16. Private NumPts As Integer ' Number of points.
  17. Private Points() As Point3D  ' Data points.
  18.  
  19. Private IsCulled As Boolean
  20.  
  21. ' ************************************************
  22. ' Draw the transformed points on a Form, Printer,
  23. ' or PictureBox. Use the API function Polygon so
  24. ' the polygon will be properly filled to cover
  25. ' polygons behind it.
  26. ' ************************************************
  27. Public Sub DrawOrdered(canvas As Object, Optional r As Variant)
  28. Dim pts() As POINTAPI
  29. Dim pt As Integer
  30. Dim status As Integer
  31.  
  32.     ' Don't draw if culled.
  33.     If IsCulled Then Exit Sub
  34.        
  35.     ' Fill in the point array.
  36.     ReDim pts(1 To NumPts)
  37.     For pt = 1 To NumPts
  38.         pts(pt).x = Points(pt).trans(1)
  39.         pts(pt).Y = Points(pt).trans(2)
  40.     Next pt
  41.  
  42.     ' Draw the polygon.
  43.     On Error Resume Next
  44.     status = Polygon(canvas.hdc, pts(1), NumPts)
  45. End Sub
  46.  
  47.  
  48. ' ************************************************
  49. ' Return the minimum and maximum coordinates.
  50. ' ************************************************
  51. Public Sub GetExtent(Xmin As Single, xmax As Single, ymin As Single, ymax As Single, zmin As Single, zmax As Single)
  52. Dim i As Integer
  53. Dim x As Single
  54. Dim Y As Single
  55. Dim z As Single
  56.  
  57.     Xmin = Points(1).trans(1)
  58.     xmax = Xmin
  59.     ymin = Points(1).trans(2)
  60.     ymax = ymin
  61.     zmin = Points(1).trans(3)
  62.     zmax = zmin
  63.     For i = 2 To NumPts
  64.         x = Points(i).trans(1)
  65.         Y = Points(i).trans(2)
  66.         z = Points(i).trans(3)
  67.         If Xmin > x Then Xmin = x
  68.         If xmax < x Then xmax = x
  69.         If ymin > Y Then ymin = Y
  70.         If ymax < Y Then ymax = Y
  71.         If zmin > z Then zmin = z
  72.         If zmax < z Then zmax = z
  73.     Next i
  74. End Sub
  75.  
  76.  
  77.  
  78.  
  79. ' ************************************************
  80. ' Return the coordinates of a point on the polygon.
  81. ' ************************************************
  82. Public Sub GetTransformedPoint(Index As Integer, x As Single, Y As Single, z As Single)
  83.     x = Points(Index).trans(1)
  84.     Y = Points(Index).trans(2)
  85.     z = Points(Index).trans(3)
  86. End Sub
  87.  
  88.  
  89.  
  90. ' ************************************************
  91. ' See where the projections of two segments cross.
  92. ' Return true if the segments cross, false
  93. ' otherwise.
  94. ' ************************************************
  95. Function FindCrossing( _
  96.     ax1 As Single, ay1 As Single, az1 As Single, _
  97.     ax2 As Single, ay2 As Single, az2 As Single, _
  98.     bx1 As Single, by1 As Single, bz1 As Single, _
  99.     bx2 As Single, by2 As Single, bz2 As Single, _
  100.     x As Single, Y As Single, z1 As Single, z2 As Single) _
  101.         As Boolean
  102. Dim dxa As Single
  103. Dim dya As Single
  104. Dim dza As Single
  105. Dim dxb As Single
  106. Dim dyb As Single
  107. Dim dzb As Single
  108. Dim t1 As Single
  109. Dim t2 As Single
  110. Dim denom As Single
  111.  
  112.     dxa = ax2 - ax1
  113.     dya = ay2 - ay1
  114.     dxb = bx2 - bx1
  115.     dyb = by2 - by1
  116.     
  117.     FindCrossing = False
  118.     
  119.     denom = dxb * dya - dyb * dxa
  120.     ' If the segments are parallel, stop.
  121.     If denom < 0.01 And denom > -0.01 Then Exit Function
  122.  
  123.     t2 = (ax1 * dya - ay1 * dxa - bx1 * dya + by1 * dxa) / denom
  124.     If t2 < 0 Or t2 > 1 Then Exit Function
  125.     
  126.     t1 = (ax1 * dyb - ay1 * dxb - bx1 * dyb + by1 * dxb) / denom
  127.     If t1 < 0 Or t1 > 1 Then Exit Function
  128.  
  129.     ' Compute the points of overlap.
  130.     x = ax1 + t1 * dxa
  131.     Y = ay1 + t1 * dya
  132.     dza = az2 - az1
  133.     dzb = bz2 - bz1
  134.     z1 = az1 + t1 * dza
  135.     z2 = bz1 + t2 * dzb
  136.     FindCrossing = True
  137. End Function
  138.  
  139.  
  140. ' ************************************************
  141. ' Return the number of points.
  142. ' ************************************************
  143. Property Get NumPoints() As Integer
  144.     NumPoints = NumPts
  145. End Property
  146.  
  147. ' ************************************************
  148. ' Return true if this polygon partially obscures
  149. ' (has greater Z value than) polygon obj.
  150. '
  151. ' We assume one polygon may obscure the other, but
  152. ' they cannot obscure each other.
  153. '
  154. ' This check is executed by seeing where the
  155. ' projections of the edges of the polygons cross.
  156. ' Where they cross, see if one Z value is greater
  157. ' than the other.
  158. '
  159. ' If no edges cross, see if one polygon contains
  160. ' the other. If so, there is an overlap.
  161. ' ************************************************
  162. Public Function Obscures(obj As ObjPolygon) As Boolean
  163. Dim num As Integer
  164. Dim i As Integer
  165. Dim j As Integer
  166. Dim xi1 As Single
  167. Dim yi1 As Single
  168. Dim zi1 As Single
  169. Dim xi2 As Single
  170. Dim yi2 As Single
  171. Dim zi2 As Single
  172. Dim xj1 As Single
  173. Dim yj1 As Single
  174. Dim zj1 As Single
  175. Dim xj2 As Single
  176. Dim yj2 As Single
  177. Dim zj2 As Single
  178. Dim x As Single
  179. Dim Y As Single
  180. Dim z1 As Single
  181. Dim z2 As Single
  182.  
  183.     num = obj.NumPoints
  184.     
  185.     ' Check each edge in this polygon.
  186.     GetTransformedPoint NumPts, xi1, yi1, zi1
  187.     For i = 1 To NumPts
  188.         GetTransformedPoint i, xi2, yi2, zi2
  189.     
  190.         ' Compare with each edge in the other.
  191.         obj.GetTransformedPoint num, xj1, yj1, zj1
  192.         For j = 1 To num
  193.             obj.GetTransformedPoint j, xj2, yj2, zj2
  194.             ' See if the segments cross.
  195.             If FindCrossing( _
  196.                 xi1, yi1, zi1, _
  197.                 xi2, yi2, zi2, _
  198.                 xj1, yj1, zj1, _
  199.                 xj2, yj2, zj2, _
  200.                 x, Y, z1, z2) _
  201.             Then
  202.                 If z1 - z2 > 0.01 Then
  203.                     ' z1 > z2. We obscure it.
  204.                     Obscures = True
  205.                     Exit Function
  206.                 End If
  207.                 If z2 - z1 > 0.01 Then
  208.                     ' z2 > z1. It obscures us.
  209.                     Obscures = False
  210.                     Exit Function
  211.                 End If
  212.             End If
  213.             
  214.             xj1 = xj2
  215.             yj1 = yj2
  216.             zj1 = zj2
  217.         Next j
  218.         
  219.         xi1 = xi2
  220.         yi1 = yi2
  221.         zi1 = zi2
  222.     Next i
  223.     
  224.     ' No edges cross. See if one polygon contains
  225.     ' the other.
  226.     
  227.     ' If any points of one polygon are inside the
  228.     ' other, then they must all be. Since the
  229.     ' IsAbove tests were inconclusive, some points
  230.     ' in one polygon are on the "bad" side of the
  231.     ' other. In that case there is an overlap.
  232.     
  233.     ' See if this polygon is inside the other.
  234.     GetTransformedPoint 1, xi1, yi1, zi1
  235.     If obj.PointInside(xi1, yi1) Then
  236.         Obscures = True
  237.         Exit Function
  238.     End If
  239.     
  240.     ' See if the other polygon is inside this one.
  241.     obj.GetTransformedPoint 1, xi1, yi1, zi1
  242.     If PointInside(xi1, yi1) Then
  243.         Obscures = True
  244.         Exit Function
  245.     End If
  246.     
  247.     Obscures = False
  248. End Function
  249.  
  250. ' ************************************************
  251. ' Return true if the point projection lies within
  252. ' this polygon's projection.
  253. ' ************************************************
  254. Function PointInside(x As Single, Y As Single) As Boolean
  255. Dim i As Integer
  256. Dim theta1 As Double
  257. Dim theta2 As Double
  258. Dim dtheta As Double
  259. Dim dx As Double
  260. Dim dy As Double
  261. Dim angles As Double
  262.  
  263.     dx = Points(NumPts).trans(1) - x
  264.     dy = Points(NumPts).trans(2) - Y
  265.     theta1 = Arctan2(CSng(dx), CSng(dy))
  266.     If theta1 < 0 Then theta1 = theta1 + 2 * PI
  267.     For i = 1 To NumPts
  268.         dx = Points(i).trans(1) - x
  269.         dy = Points(i).trans(2) - Y
  270.         theta2 = Arctan2(CSng(dx), CSng(dy))
  271.         If theta2 < 0 Then theta2 = theta2 + 2 * PI
  272.         dtheta = theta2 - theta1
  273.         If dtheta > PI Then dtheta = dtheta - 2 * PI
  274.         If dtheta < -PI Then dtheta = dtheta + 2 * PI
  275.         angles = angles + dtheta
  276.         theta1 = theta2
  277.     Next i
  278.     
  279.     PointInside = (Abs(angles) > 0.001)
  280. End Function
  281.  
  282. ' ************************************************
  283. ' Return true if this polygon is completly below
  284. ' the plane containing obj.
  285. ' ************************************************
  286. Public Function IsBelow(obj As ObjPolygon) As Boolean
  287. Dim nx As Single
  288. Dim ny As Single
  289. Dim nz As Single
  290. Dim px As Single
  291. Dim py As Single
  292. Dim pz As Single
  293. Dim dx As Single
  294. Dim dy As Single
  295. Dim dz As Single
  296. Dim cx As Single
  297. Dim cy As Single
  298. Dim cz As Single
  299. Dim i As Integer
  300.  
  301.     ' Compute a downward pointing normal to the plane.
  302.     obj.TransformedNormalVector nx, ny, nz
  303.     If nz > 0 Then
  304.         nx = -nx
  305.         ny = -ny
  306.         nz = -nz
  307.     End If
  308.     
  309.     ' Get a point on the plane.
  310.     obj.GetTransformedPoint 1, px, py, pz
  311.     
  312.     ' See if the points in this polygon all lie
  313.     For i = 1 To NumPts
  314.         ' Get the vector from plane to point.
  315.         dx = Points(i).trans(1) - px
  316.         dy = Points(i).trans(2) - py
  317.         dz = Points(i).trans(3) - pz
  318.             
  319.         ' If the dot product < 0, the point is
  320.         ' below the plane.
  321.         If dx * nx + dy * ny + dz * nz < -0.01 Then
  322.             IsBelow = False
  323.             Exit Function
  324.         End If
  325.     Next i
  326.     IsBelow = True
  327. End Function
  328.  
  329.  
  330. ' ************************************************
  331. ' Return true if this polygon is completly above
  332. ' the plane containing obj.
  333. ' ************************************************
  334. Public Function IsAbove(obj As ObjPolygon) As Boolean
  335. Dim nx As Single
  336. Dim ny As Single
  337. Dim nz As Single
  338. Dim px As Single
  339. Dim py As Single
  340. Dim pz As Single
  341. Dim dx As Single
  342. Dim dy As Single
  343. Dim dz As Single
  344. Dim cx As Single
  345. Dim cy As Single
  346. Dim cz As Single
  347. Dim i As Integer
  348.  
  349.     ' Compute an upward pointing normal to the plane.
  350.     obj.TransformedNormalVector nx, ny, nz
  351.     If nz < 0 Then
  352.         nx = -nx
  353.         ny = -ny
  354.         nz = -nz
  355.     End If
  356.     
  357.     ' Get a point on the plane.
  358.     obj.GetTransformedPoint 1, px, py, pz
  359.     
  360.     ' See if the points in this polygon all lie
  361.     For i = 1 To NumPts
  362.         ' Get the vector from plane to point.
  363.         dx = Points(i).trans(1) - px
  364.         dy = Points(i).trans(2) - py
  365.         dz = Points(i).trans(3) - pz
  366.             
  367.         ' If the dot product < 0, the point is
  368.         ' below the plane.
  369.         If dx * nx + dy * ny + dz * nz < -0.01 Then
  370.             IsAbove = False
  371.             Exit Function
  372.         End If
  373.     Next i
  374.     IsAbove = True
  375. End Function
  376.  
  377.  
  378. ' ***********************************************
  379. ' Return the maximum transformed Z value for this
  380. ' object.
  381. ' ***********************************************
  382. Property Get zmax() As Single
  383. Dim best As Single
  384. Dim z As Single
  385. Dim i As Integer
  386.  
  387.     best = Points(1).trans(3)
  388.     For i = 2 To NumPts
  389.         z = Points(i).trans(3)
  390.         If best < z Then best = z
  391.     Next i
  392.     zmax = best
  393. End Property
  394.  
  395.  
  396.  
  397.  
  398. ' ***********************************************
  399. ' Create a polyline representing the normal to
  400. ' this polygon and place it in the given objects
  401. ' collection.
  402. ' ***********************************************
  403. Sub CreateNormal(Objects As Collection)
  404. Dim pline As New ObjPolyline
  405. Dim x1 As Single
  406. Dim y1 As Single
  407. Dim z1 As Single
  408. Dim x2 As Single
  409. Dim y2 As Single
  410. Dim z2 As Single
  411.  
  412.     Objects.Add pline
  413.     UnitNormalSegment x1, y1, z1, x2, y2, z2
  414.     pline.AddSegment x1, y1, z1, x2, y2, z2
  415. End Sub
  416.  
  417. ' ***********************************************
  418. ' Compute a transformed normal vector.
  419. ' ***********************************************
  420. Public Sub TransformedNormalVector(nx As Single, ny As Single, nz As Single)
  421. Dim Ax As Single
  422. Dim Ay As Single
  423. Dim Az As Single
  424. Dim Bx As Single
  425. Dim By As Single
  426. Dim Bz As Single
  427.  
  428.     Ax = Points(2).trans(1) - Points(1).trans(1)
  429.     Ay = Points(2).trans(2) - Points(1).trans(2)
  430.     Az = Points(2).trans(3) - Points(1).trans(3)
  431.     Bx = Points(3).trans(1) - Points(2).trans(1)
  432.     By = Points(3).trans(2) - Points(2).trans(2)
  433.     Bz = Points(3).trans(3) - Points(2).trans(3)
  434.     m3Cross nx, ny, nz, Ax, Ay, Az, Bx, By, Bz
  435. End Sub
  436.  
  437.  
  438.  
  439. ' ***********************************************
  440. ' Compute a normal vector for this polygon.
  441. ' ***********************************************
  442. Public Sub NormalVector(nx As Single, ny As Single, nz As Single)
  443. Dim Ax As Single
  444. Dim Ay As Single
  445. Dim Az As Single
  446. Dim Bx As Single
  447. Dim By As Single
  448. Dim Bz As Single
  449.  
  450.     Ax = Points(2).coord(1) - Points(1).coord(1)
  451.     Ay = Points(2).coord(2) - Points(1).coord(2)
  452.     Az = Points(2).coord(3) - Points(1).coord(3)
  453.     Bx = Points(3).coord(1) - Points(2).coord(1)
  454.     By = Points(3).coord(2) - Points(2).coord(2)
  455.     Bz = Points(3).coord(3) - Points(2).coord(3)
  456.     m3Cross nx, ny, nz, Ax, Ay, Az, Bx, By, Bz
  457. End Sub
  458.  
  459.  
  460.  
  461.  
  462. ' ***********************************************
  463. ' Compute the unit normal line segment for this
  464. ' polygon.
  465. ' ***********************************************
  466. Sub UnitNormalSegment(x1 As Single, y1 As Single, z1 As Single, x2 As Single, y2 As Single, z2 As Single)
  467. Dim i As Integer
  468. Dim nx As Single
  469. Dim ny As Single
  470. Dim nz As Single
  471.     
  472.     UnitNormalVector nx, ny, nz
  473.     
  474.     x1 = 0
  475.     y1 = 0
  476.     z1 = 0
  477.     For i = 1 To NumPts
  478.         x1 = x1 + Points(i).coord(1)
  479.         y1 = y1 + Points(i).coord(2)
  480.         z1 = z1 + Points(i).coord(3)
  481.     Next i
  482.     x1 = x1 / NumPts
  483.     y1 = y1 / NumPts
  484.     z1 = z1 / NumPts
  485.  
  486.     x2 = x1 + nx
  487.     y2 = y1 + ny
  488.     z2 = z1 + nz
  489. End Sub
  490.  
  491.  
  492. ' ***********************************************
  493. ' Compute the unit normal vector for this
  494. ' polygon.
  495. ' ***********************************************
  496. Sub UnitNormalVector(nx As Single, ny As Single, nz As Single)
  497. Dim D As Single
  498.  
  499.     NormalVector nx, ny, nz
  500.     D = Sqr(nx * nx + ny * ny + nz * nz)
  501.     nx = nx / D
  502.     ny = ny / D
  503.     nz = nz / D
  504. End Sub
  505.  
  506.  
  507.  
  508.  
  509.  
  510. ' ***********************************************
  511. ' Set or clear the IsCulled flag.
  512. ' ***********************************************
  513. Property Let Culled(value As Boolean)
  514.     IsCulled = value
  515. End Property
  516.  
  517.  
  518. ' ***********************************************
  519. ' Return true if the polygon has been culled.
  520. ' ***********************************************
  521. Property Get Culled() As Boolean
  522.     Culled = IsCulled
  523. End Property
  524.  
  525. ' ***********************************************
  526. ' Return a string indicating the object type.
  527. ' ***********************************************
  528. Property Get ObjectType() As String
  529.     ObjectType = "POLYGON"
  530. End Property
  531.  
  532. ' ************************************************
  533. ' Add one or more points to the polygon.
  534. ' ************************************************
  535. Public Sub AddPoint(ParamArray coord() As Variant)
  536. Dim num_pts As Integer
  537. Dim i As Integer
  538. Dim pt As Integer
  539.  
  540.     num_pts = (UBound(coord) + 1) \ 3
  541.     ReDim Preserve Points(1 To NumPts + num_pts)
  542.  
  543.     pt = 0
  544.     For i = 1 To num_pts
  545.         Points(NumPts + i).coord(1) = coord(pt)
  546.         Points(NumPts + i).coord(2) = coord(pt + 1)
  547.         Points(NumPts + i).coord(3) = coord(pt + 2)
  548.         Points(NumPts + i).coord(4) = 1#
  549.         pt = pt + 3
  550.     Next i
  551.  
  552.     NumPts = NumPts + num_pts
  553. End Sub
  554.  
  555.  
  556.  
  557. ' ***********************************************
  558. ' Fix the data coordinates at their transformed
  559. ' values.
  560. ' ***********************************************
  561. Public Sub FixPoints()
  562. Dim i As Integer
  563. Dim j As Integer
  564.  
  565.     For i = 1 To NumPts
  566.         For j = 1 To 3
  567.             Points(i).coord(j) = Points(i).trans(j)
  568.         Next j
  569.     Next i
  570. End Sub
  571.  
  572. ' ************************************************
  573. ' Apply a transformation matrix which may not
  574. ' contain 0, 0, 0, 1 in the last column to the
  575. ' object.
  576. ' ************************************************
  577. Public Sub ApplyFull(M() As Single)
  578. Dim i As Integer
  579.  
  580.     If IsCulled Then Exit Sub
  581.     For i = 1 To NumPts
  582.         m3ApplyFull Points(i).coord, M, Points(i).trans
  583.     Next i
  584. End Sub
  585.  
  586. ' ************************************************
  587. ' Apply a transformation matrix to the object.
  588. ' ************************************************
  589. Public Sub Apply(M() As Single)
  590. Dim i As Integer
  591.  
  592.     If IsCulled Then Exit Sub
  593.     For i = 1 To NumPts
  594.         m3Apply Points(i).coord, M, Points(i).trans
  595.     Next i
  596. End Sub
  597.  
  598.  
  599. ' ************************************************
  600. ' Apply a nonlinear transformation.
  601. ' ************************************************
  602. Public Sub Distort(D As Object)
  603. Dim i As Integer
  604.  
  605.     For i = 1 To NumPts
  606.         D.Distort Points(i).coord(1), Points(i).coord(2), Points(i).coord(3)
  607.     Next i
  608. End Sub
  609.  
  610. ' ************************************************
  611. ' Write a polyline to a file using Write.
  612. ' Begin with "POLYGON" to identify this object.
  613. ' ************************************************
  614. Public Sub FileWrite(filenum As Integer)
  615. Dim i As Integer
  616.  
  617.     Write #filenum, "POLYGON", NumPts
  618.     
  619.     ' Write the points.
  620.     For i = 1 To NumPts
  621.         Write #filenum, Points(i).coord(1), Points(i).coord(2), Points(i).coord(3)
  622.     Next i
  623. End Sub
  624.  
  625. ' ************************************************
  626. ' Draw the transformed points on a Form, Printer,
  627. ' or PictureBox.
  628. ' ************************************************
  629. Public Sub Draw(canvas As Object, Optional r As Variant)
  630. Dim pt As Integer
  631.  
  632.     ' Don't draw if culled.
  633.     If IsCulled Then Exit Sub
  634.     
  635.     On Error Resume Next
  636.     canvas.CurrentX = Points(NumPts).trans(1)
  637.     canvas.CurrentY = Points(NumPts).trans(2)
  638.     For pt = 1 To NumPts
  639.         canvas.Line _
  640.             -(Points(pt).trans(1), Points(pt).trans(2))
  641.     Next pt
  642. End Sub
  643. ' ***********************************************
  644. ' Cull if any points are behind the center of
  645. ' projection.
  646. ' ***********************************************
  647. Public Sub ClipEye(r As Single)
  648. Dim pt As Integer
  649.  
  650.     If IsCulled Then Exit Sub
  651.     For pt = 1 To NumPts
  652.         If Points(pt).trans(3) >= r Then Exit For
  653.     Next pt
  654.     If pt <= NumPts Then IsCulled = True
  655. End Sub
  656. ' ***********************************************
  657. ' Perform backface removal.
  658. ' ***********************************************
  659. Public Sub Cull(x As Single, Y As Single, z As Single)
  660. Dim Ax As Single
  661. Dim Ay As Single
  662. Dim Az As Single
  663. Dim nx As Single
  664. Dim ny As Single
  665. Dim nz As Single
  666.  
  667.     ' Compute a normal to the face.
  668.     NormalVector nx, ny, nz
  669.  
  670.     ' Compute a vector from the center of
  671.     ' projection to the face.
  672.     Ax = Points(1).coord(1) - x
  673.     Ay = Points(1).coord(2) - Y
  674.     Az = Points(1).coord(3) - z
  675.     
  676.     ' See if the vectors meet at an angle < 90.
  677.     IsCulled = (Ax * nx + Ay * ny + Az * nz > -0.0001)
  678. End Sub
  679.  
  680. ' ************************************************
  681. ' Read a polyline from a file using Input.
  682. ' Assume the "POLYGON" label has already been
  683. ' read.
  684. ' ************************************************
  685. Public Sub FileInput(filenum As Integer)
  686. Dim i As Integer
  687.  
  688.     Input #filenum, NumPts
  689.     
  690.     ' Allocate and read the points.
  691.     ReDim Points(1 To NumPts)
  692.     For i = 1 To NumPts
  693.         Input #filenum, Points(i).coord(1), Points(i).coord(2), Points(i).coord(3)
  694.         Points(i).coord(4) = 1#
  695.     Next i
  696. End Sub
  697.  
  698.  
  699.